import { DefaultResponse } from "@iboot-vue/common";

export class Error {
  code: string;
  msg: string;
  detail?: string;
  constructor(code: string, msg: string, detail?: string) {
    this.code = code;
    this.msg = msg;
    if (detail) {
      this.detail = detail;
    }
  }
}
export class Result<T> {
  success: boolean;
  msg: string;
  data?: T;
  error?: Error;
  constructor(success: boolean, msg: string, data?: T, error?: Error) {
    this.success = success;
    this.msg = msg;
    if (data) {
      this.data = data;
    }
    if (error) {
      this.error = error;
    }
  }
}
export type Page = {
  pageNumber: number;
  pageSize: number;
  totalCount?: number;
}

export type PageModel<T> = {
  records: T[];
} & Page;

export const ibootSimpleResponseObject = <T>(request: Promise<DefaultResponse>,
  failCallBack?: (data: Result<T> | string) => void
): Promise<T> => {
  return  ibootResponseObject(ibootResponse<T>(request), failCallBack);
};

export const ibootSimpleResponseString = (request: Promise<DefaultResponse>
): Promise<string> => {
  return ibootResponseString(ibootResponse<string>(request));
};


export const ibootResponseObject = <T>(
  result: Promise<Result<T>>,
  failCallBack?: (data: Result<T> | string) => void
): Promise<T> => {
  return new Promise(async (resolve, reject) => {
    return result
      .then(resp => {
        if (resp.success) {
          resolve(resp.data);
        } else {
          failCallBack?.(resp);
          reject(resp);
        }
      })
      .catch(e => {
        failCallBack?.(e);
        reject(e);
      });
  });
};


export const ibootResponseString = <T>(result: Promise<Result<T>>): Promise<string> => {
  return new Promise(async (resolve, reject) => {
    return result
      .then(resp => {
        if (resp.success) {
          resolve(resp.msg);
        } else {
          reject(resp.msg || resp.error.msg || resp.error.detail);
        }
      })
      .catch(e => {
        reject(e);
      });
  });
};


export const ibootResponse = <T>(request: Promise<DefaultResponse>): Promise<Result<T>> => {
  return new Promise(async (resolve, reject) => {
    return request
      .then(resp => {
        if (resp.status && resp.data) {
          const data = resp.data as Result<T>;
          resolve(new Result(true, data.msg || '', data.data, data.error));
        }
        reject(resp.msg);
      })
      .catch(e => {
        reject(typeof e === 'string' ? e : JSON.stringify(e));
      });
  });
};